package com.example.spring5.Spring5新特性.Webflux新功能;

import com.example.spring5.Spring5新特性.Webflux新功能.函数式编程模型.UserLong;
import com.example.spring5.Spring5新特性.Webflux新功能.函数式编程模型.UserLongHandler;
import com.example.spring5.Spring5新特性.Webflux新功能.函数式编程模型.UserLongService;
import com.example.spring5.Spring5新特性.Webflux新功能.函数式编程模型.UserLongServiceImpl;
import com.example.springDemo.SpringDemoApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.netty.http.server.HttpServer;

import java.io.IOException;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;

/**
 * （1）在使用函数式编程模型操作时候，需要自己初始化服务器
 * （2）基于函数式编程模型时候，有两个核心接口：
 *      RouterFunction（实现路由功能，请求转发给对应的 handler）和
 *      HandlerFunction（处理请求生成响应的函数）。
 *      核心任务定义两个函数式接口的实现并且启动需要的服务器。
 * （ 3 ） SpringWebflux 请求和响应不再是ServletRequest和ServletResponse ，
 *        而是ServerRequest 和 ServerResponse
 *
 *  第一步 把注解编程模型工程复制一份 ，保留 entity 和 service 内容
 * 第二步 创建 Handler（具体实现方法）
 * 第三步 初始化服务器，编写 Router
 *    ⚫ 创建路由的方法
 */

public class 基于函数式编程模型 { //
    //多用了两个类 Server.java    UserLongHandler.java
    public static void main(String[] args)  {
//        基于函数式编程模型网页调用();
        //执行基于函数式编程模型网页调用  按理(现在是失败情况)说会出现一个端口号
        WebClient webClient = WebClient.create("http://127.0.0.1:端口号");
         UserLong block = webClient.get().
                 uri("/users/{id}", "1")
                .accept(APPLICATION_JSON)
                .retrieve().bodyToMono(UserLong.class)
                .block();
        System.out.println(block);//可以获取信息

        Flux<UserLong> userLongFlux = webClient.get().
                uri("/users")
                .accept(APPLICATION_JSON)
                .retrieve().bodyToFlux(UserLong.class);

        userLongFlux.map(stu ->stu.getUsername())
                .buffer().doOnNext(System.out::println)
                .blockFirst();

    }

    private static void 基于函数式编程模型网页调用() {//执行失败  需要单独创建项目
        基于函数式编程模型 s = new 基于函数式编程模型();
        s.createReactorServer();
        System.out.println("调用");
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //1 创建Router路由
    public RouterFunction<ServerResponse> routingFunction() {
        //创建hanler对象
        UserLongService userService = new UserLongServiceImpl();
        UserLongHandler handler = new UserLongHandler(userService);
        //设置路由
        return RouterFunctions.route(
                        GET("/users/{id}").and(accept(APPLICATION_JSON)),handler::getUserLongById)
                .andRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUserLong);
    }

    //2 创建服务器完成适配
    public void createReactorServer() {
        //路由和handler适配
        RouterFunction<ServerResponse> route = routingFunction();
        HttpHandler httpHandler = toHttpHandler(route);
        ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
        //创建服务器
        HttpServer httpServer = HttpServer.create();
        httpServer.handle(adapter).bindNow();
    }
}

